package cn.unknowpupil.controller.system;

import cn.unknowpupil.common.core.annotation.Log;
import cn.unknowpupil.common.core.annotation.RunTime;
import cn.unknowpupil.common.core.configure.FileProperties;
import cn.unknowpupil.common.core.constant.SecurityConstants;
import cn.unknowpupil.common.core.enums.BusinessType;
import cn.unknowpupil.common.core.exceptions.HealthException;
import cn.unknowpupil.common.core.resopnse.ResultResponse;
import cn.unknowpupil.common.core.utils.FileUtil;
import cn.unknowpupil.common.core.utils.StringUtils;
import cn.unknowpupil.common.security.component.TokenService;
import cn.unknowpupil.common.security.dto.LoginUser;
import cn.unknowpupil.common.security.utils.SecurityUtils;
import cn.unknowpupil.domain.system.SysRole;
import cn.unknowpupil.domain.system.SysUser;
import cn.unknowpupil.service.system.ISysPostService;
import cn.unknowpupil.service.system.ISysRoleService;
import cn.unknowpupil.service.system.ISysUserService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Created at 2020-10-16 by  w10g <br>
 * Initialize SysUser  ... <br>
 * 管理员信息表 视图浏览层处理
 *
 * @author unknowpupil
 * @since 0.0.1
 */
@Api(tags = {"系统-管理员信息表模块"}, value = "sys-user")
@RestController
@RequestMapping(value = "admin/sys-user")
@RequiredArgsConstructor
public class SysUserController {

    private final ISysRoleService roleService;
    private final ISysPostService postService;
    private final ISysUserService sysUserService;
    private final TokenService tokenService;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    /**
     * 新增
     *
     * @param SysUser {@link SysUser}  用户信息表
     * @return {@link ResultResponse}
     */
    @ApiOperation("系统：新增")
    @Log(title = "create", businessType = BusinessType.INSERT)
    @PostMapping("create")
    public ResultResponse create(@Valid @RequestBody SysUser SysUser, BindingResult bindingResult) {
        // 表单验证
        if (bindingResult.hasErrors()) {
            return ResultResponse.buildFailure(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }

        // 业务逻辑
        boolean created = sysUserService.create(SysUser);
        if (created) {
            return ResultResponse.success("创建成功");
        } else {
            return ResultResponse.buildFailure("创建失败");
        }

    }

    /**
     * 修改
     *
     * @param SysUser {@link SysUser}  用户信息表
     * @return {@link ResultResponse}
     */
    @RunTime(describe = "修改用户信息表")
    @PutMapping("update")
    public ResultResponse update(@Validated @RequestBody SysUser SysUser) {

        // 业务逻辑
        boolean update = sysUserService.update(SysUser);
        if (update) {
            return ResultResponse.success("修改成功");
        } else {
            return ResultResponse.buildFailure("修改失败");
        }

    }


    /**
     * 根据用户编号获取详细信息
     */
    @ApiOperation("系统：查询用户")
    @RunTime(describe = "根据用户编号获取详细信息")
    @GetMapping(value = {"get/", "get/{userId}"})
    public ResultResponse getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        Map<String, Object> map = Maps.newHashMap();

        List<SysRole> roles = roleService.selectRoleAll();
        map.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        map.put("posts", postService.selectPostAll());
        if (StringUtils.isNotNull(userId)) {
            map.put("user", sysUserService.getById(userId));
            map.put("postIds", postService.selectPostListByUserId(userId));
            map.put("roleIds", roleService.selectRoleListByUserId(userId));
        }
        return ResultResponse.buildSuccess(map);
    }

    /**
     * 删除
     *
     * @param ids {@code Long}
     * @return {@link ResultResponse}
     */
    @ApiOperation("系统：删除用户")
    @DeleteMapping("remove/{ids}")
    public ResultResponse remove(@PathVariable("ids") Long[] ids) {
        // 业务逻辑
        boolean deleted = sysUserService.delete(ids);
        if (deleted) {
            return ResultResponse.success("删除成功");
        } else {
            return ResultResponse.buildFailure("删除失败");
        }
    }

    /**
     * 分页
     *
     * @param current {@code int} 页码
     * @param size    {@code int} 笔数
     * @return {@link ResultResponse}
     */
    @ApiOperation("系统：分页查询用户")
    @GetMapping("page/{current}/{size}")
    @RunTime(describe = "查询用户")
    public ResultResponse<IPage<SysUser>> page(@PathVariable("current") int current, @PathVariable("size") int size, @ModelAttribute SysUser SysUser) {
        IPage<SysUser> page = sysUserService.page(current, size, SysUser);
        return ResultResponse.buildSuccess(page);
    }

    @ApiOperation("系统：重置密码")
    @PutMapping("change/password")
    public ResultResponse<IPage<SysUser>> changePwd(@RequestBody SysUser user) {
        boolean b = sysUserService.changePwd(user);
        if (b) {
            return ResultResponse.success("修改密码成功");
        } else {
            return ResultResponse.buildFailure("修改密码失败");
        }
    }

    @ApiOperation("系统：修改状态")
    @PutMapping("change/status")
    public ResultResponse<IPage<SysUser>> changeStatus(@RequestBody SysUser user) {
        boolean b = sysUserService.changeStatus(user);
        if (b) {
            return ResultResponse.success("修改状态成功");
        } else {
            return ResultResponse.buildFailure("修改状态失败");
        }
    }

    @ApiOperation("系统：个人信息")
    @GetMapping("profile")
    public ResultResponse profile() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = sysUserService.getById(loginUser.getId());
        Map<String, Object> map = Maps.newHashMap();
        map.put("user", user);
        map.put("roleGroup", sysUserService.selectUserRoleGroup(loginUser.getId()));
        map.put("postGroup", sysUserService.selectUserPostGroup(loginUser.getId()));
        return ResultResponse.buildSuccess(map);

    }

    @ApiOperation("系统：个人信息")
    @Log(title = "修改个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("profile")
    public ResultResponse editProfile(@RequestBody SysUser sysUser) {
        boolean user = sysUserService.editProfile(sysUser);
        if (user) {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            // 更新缓存用户信息
            loginUser.setUsername(sysUser.getUserName());
            tokenService.refreshToken(loginUser);
            return ResultResponse.success("修改成功");
        }
        return ResultResponse.buildFailure("修改个人信息异常，请联系管理员");

    }

    /**
     * 重置密码
     */
    @Log(title = "修改密码", businessType = BusinessType.UPDATE)
    @PutMapping("profile/reset/password")
    public ResultResponse updatePwd(String oldPassword, String newPassword) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String password = loginUser.getPassword();
        boolean matches = bCryptPasswordEncoder.matches(oldPassword, password);
        if (!matches) {
            return ResultResponse.buildFailure("修改密码失败，旧密码错误");
        }
        matches = bCryptPasswordEncoder.matches(newPassword, password);

        if (matches) {
            return ResultResponse.buildFailure("新密码不能与旧密码相同");
        }
        SysUser user = new SysUser();
        user.setId(loginUser.getId());
        user.setPassword(newPassword);

        if (sysUserService.changePwd(user)) {
            // 更新缓存用户密码
            loginUser.setPassword(bCryptPasswordEncoder.encode(newPassword));
            tokenService.refreshToken(loginUser);
            return ResultResponse.success("修改成功");
        }
        return ResultResponse.buildFailure("修改密码异常，请联系管理员");
    }


    @Log(title = "用户头像", businessType = BusinessType.UPDATE)
    @PostMapping("profile/avatar")
    @ApiOperation("用户头像")
    public ResultResponse upload(@RequestParam("avatarFile") MultipartFile avatarFile) throws IOException {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String path = sysUserService.updateAvatar(avatarFile, loginUser.getId());
        return ResultResponse.buildSuccess(path);

    }
}
